package coneccion;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Savepoint;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;

import javax.naming.NamingException;

import objetos.Estudiante;
import objetos.Rol;
import objetos.Usuario;


import utils.Constantes;
import utils.UtilidadesConexion;

public class PropiedadesSistemaConsultas {

	public PropiedadesSistemaConsultas() {
		super();
	}

	public String getEstadoVotacion(){
		String result = null;
		Connection con = null;
		Statement stmt = null;
		ResultSet rs = null;
		StringBuilder query = new StringBuilder("");
		
		try {
			//creo la coneccion y la sentencia
			con = UtilidadesConexion.getConnectionFromTomcatPool();
			con.setAutoCommit(true);
			stmt = con.createStatement();
			
			//creo la consulta
			query.append("SELECT DISTINCT propiedades_sistema_valor ");
			query.append("FROM propiedades_sistema ");
			query.append("WHERE  propiedades_sistema_nombre='estado_votacion' ");
			
			//ejecuto la consulta y guardo el resultado en el resultset
			rs = stmt.executeQuery(query.toString());
			
			if(rs.first()){
				result = rs.getString("propiedades_sistema_valor");
			}
			
			if ( !Constantes.ESTADO_VOTACION_FINALIZADA.equals(result) 
					&& !Constantes.ESTADO_VOTACION_INICIADA.equals(result)
					&& !Constantes.ESTADO_VOTACION_PREPARACION.equals(result) ){ 							
				result = Constantes.ESTADO_VOTACION_FINALIZADA;
			}
			
		} catch (NamingException e) {
			e.printStackTrace();
			result = Constantes.ESTADO_VOTACION_FINALIZADA;
		} catch (SQLException e) {
			e.printStackTrace();
			result = Constantes.ESTADO_VOTACION_FINALIZADA;
		} catch (Exception e) {
			e.printStackTrace();
			result = Constantes.ESTADO_VOTACION_FINALIZADA;
		} finally {
			if (rs != null) {
			      try { 
			    	  rs.close(); 
			      } catch (SQLException e) {
			    	  
			      }
			      rs = null;
		    }
		    if (stmt != null) {
		      try { 
		    	  	stmt.close();
		    	  } catch (SQLException e) {
		    		  
		    	  }
		      stmt = null;
		    }
			if(con!=null){
				try {
					con.close();
				} catch (SQLException e) {
					
				}
				con = null;
			}
		}
		
		return result;
	}
	
	public synchronized static Boolean setEstadoVotacion(String estadoVotacion){
		Boolean result = Boolean.FALSE;
		Connection con = null;

		try {
			//creo la coneccion y  un punto de restauracion en la base de datos
			con = UtilidadesConexion.getConnectionFromTomcatPool();
			con.setAutoCommit(false);
			
			if(Constantes.ESTADO_VOTACION_INICIADA.equals(estadoVotacion)){
				
				if(Constantes.ESTADO_VOTACION_PREPARACION.equals(PropiedadesSistemaConsultas.verificarEstadoVotacionSinc())){
					
					Integer numeroEstudiantes = PropiedadesSistemaConsultas.contarEstudiantesSinc();
					Integer numeroPresidentesMesas = PropiedadesSistemaConsultas.contarPresidentesMesasSinc();
					Integer cantidadEstudiantesPorMesas = Integer.valueOf(10);
					Integer cantidadEstudiantesUltimaMesa = Integer.valueOf(10+1);
					List<String> idsPresidentesMesas = PropiedadesSistemaConsultas.getPresidentesMesasIdsSinc();
					if(numeroPresidentesMesas.intValue()>0 && numeroEstudiantes.intValue()>0 && idsPresidentesMesas!=null && idsPresidentesMesas.size()>0){
						
						cantidadEstudiantesPorMesas = numeroEstudiantes.intValue()/numeroPresidentesMesas.intValue();
						cantidadEstudiantesUltimaMesa = cantidadEstudiantesPorMesas.intValue() + numeroEstudiantes.intValue()%numeroPresidentesMesas.intValue();
						if(cantidadEstudiantesPorMesas.intValue()<10){
							cantidadEstudiantesPorMesas = Integer.valueOf(10);
						}
						
						if(cantidadEstudiantesUltimaMesa.intValue()<10){
							cantidadEstudiantesUltimaMesa= Integer.valueOf(10+1);
						}
						
						Boolean resetearEstudiantes = PropiedadesSistemaConsultas.resetearEstadoEstudiantesSinc(con);
						Boolean limpiarMesas = PropiedadesSistemaConsultas.limpiarMesasSinc(con);
						Boolean agregarMesas = PropiedadesSistemaConsultas.agregarMesasSinc(con, idsPresidentesMesas);
						Boolean asignarVotantesMesas = PropiedadesSistemaConsultas.asignarEstudiantesMesasSinc(con, numeroPresidentesMesas, cantidadEstudiantesPorMesas, cantidadEstudiantesUltimaMesa);
						Boolean resetearVotos = PropiedadesSistemaConsultas.resetearVotosSinc(con);
						Boolean votacionIniciada = PropiedadesSistemaConsultas.setEstadoVotacionSinc(con, Constantes.ESTADO_VOTACION_INICIADA);
						
						result = resetearEstudiantes && limpiarMesas && agregarMesas && asignarVotantesMesas && resetearVotos && votacionIniciada;
						
						if(result){
							con.commit();
						}
					}
				}
				
			} else if(Constantes.ESTADO_VOTACION_FINALIZADA.equals(estadoVotacion)){
				
				if(Constantes.ESTADO_VOTACION_INICIADA.equals(PropiedadesSistemaConsultas.verificarEstadoVotacionSinc())){
					result = PropiedadesSistemaConsultas.setEstadoVotacionSinc(con, Constantes.ESTADO_VOTACION_FINALIZADA);
					if(result){
						con.commit();
					}
				}
				
			}else if(Constantes.ESTADO_VOTACION_PREPARACION.equals(estadoVotacion)){
				
				if(Constantes.ESTADO_VOTACION_FINALIZADA.equals(PropiedadesSistemaConsultas.verificarEstadoVotacionSinc())){
					result = PropiedadesSistemaConsultas.setEstadoVotacionSinc(con, Constantes.ESTADO_VOTACION_PREPARACION);
					if(result){
						con.commit();
					}
				}
				
			}
		
			if(result.booleanValue()==false){
				try {
					if(con!=null ){
						con.rollback();
					}
				} catch (SQLException e1) {
					// TODO Auto-generated catch block
					e1.printStackTrace();
				}
			}
			
		} catch (SQLException e) {
			e.printStackTrace();
			//rollback a la transaccion
			try {
				if(con!=null ){
					con.rollback();
				}
			} catch (SQLException e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			}
			result = Boolean.FALSE;
		} catch (Exception e) {
			e.printStackTrace();
			//rollback a la transaccion
			try {
				if(con!=null ){
					con.rollback();
				}
			} catch (SQLException e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			} 
			result = Boolean.FALSE;
		} finally {
			if(con!=null){
				try {
					con.close();
				} catch (SQLException e) {
					
				}
				con = null;
			}
		}
		return result;
	}
	
	private synchronized static String verificarEstadoVotacionSinc(){
		String result = null;
		Statement stmt = null;
		ResultSet rs = null;
		StringBuilder query = new StringBuilder("");
		Connection con = null;
		try {
			//creo la coneccion y la sentencia
			con = UtilidadesConexion.getConnectionFromTomcatPool();
			con.setAutoCommit(true);
			stmt = con.createStatement();
			
			//creo la consulta
			query.append("SELECT DISTINCT propiedades_sistema_valor ");
			query.append("FROM propiedades_sistema ");
			query.append("WHERE  propiedades_sistema_nombre='estado_votacion' ");
			
			//ejecuto la consulta y guardo el resultado en el resultset
			rs = stmt.executeQuery(query.toString());
			
			if(rs.first()){
				result = rs.getString("propiedades_sistema_valor");
			}
			
			if ( !Constantes.ESTADO_VOTACION_FINALIZADA.equals(result) 
					&& !Constantes.ESTADO_VOTACION_INICIADA.equals(result)
					&& !Constantes.ESTADO_VOTACION_PREPARACION.equals(result) ){ 							
				result = Constantes.ESTADO_VOTACION_FINALIZADA;
			}
			
		} catch (NamingException e) {
			e.printStackTrace();
			result = null;
		} catch (SQLException e) {
			e.printStackTrace();
			result = null;
		} catch (Exception e) {
			e.printStackTrace();
			result = null;
		} finally {
			if (rs != null) {
			      try { 
			    	  rs.close(); 
			      } catch (SQLException e) {
			    	  
			      }
			      rs = null;
		    }
		    if (stmt != null) {
		      try { 
		    	  	stmt.close();
		    	  } catch (SQLException e) {
		    		  
		    	  }
		      stmt = null;
		    }
			if(con!=null){
				try {
					con.close();
				} catch (SQLException e) {
					
				}
				con = null;
			}
		}
		
		return result;
	}
	
	private synchronized static Boolean resetearEstadoEstudiantesSinc(Connection con) throws SQLException{
		Boolean result = Boolean.FALSE;
		PreparedStatement stmt = null;
		StringBuffer query = new StringBuffer("");
		
		try {
			//creo la consulta
			query.append("UPDATE estudiantes ")
			.append("SET estudiantes_codigo_votacion='', ")
			.append("estudiantes_estado_voto=0, ")
			.append("estudiantes_numero_mesa=? ");
			
			stmt = con.prepareStatement(query.toString());
			stmt.setNull(1, java.sql.Types.INTEGER);
			//ejecuto la consulta y guardo el resultado en el resultset
			stmt.executeUpdate();
		
			result = Boolean.TRUE;
		}finally {
			
		    if (stmt != null) {
		      try { 
		    	  	stmt.close();
		    	  } catch (SQLException e) {
		    		  
		    	  }
		      stmt = null;
		    }
			
		}
	
		
		return result;
	}
	
	private synchronized static Integer contarEstudiantesSinc(){
		Integer result = Integer.valueOf(0);
		Statement stmt = null;
		ResultSet rs = null;
		StringBuilder query = new StringBuilder("");		
		Connection con = null;
		try {
			//creo la coneccion y la sentencia
			con = UtilidadesConexion.getConnectionFromTomcatPool();
			con.setAutoCommit(true);
			stmt = con.createStatement();
			
			//creo la consulta
			query.append("SELECT DISTINCT count(*) as cantidad ");
			
			query.append("FROM estudiantes e ");
			
			//ejecuto la consulta y guardo el resultado en el resultset
			rs = stmt.executeQuery(query.toString());
			if(rs.next()){
				result = rs.getInt("cantidad") ;
			}
		} catch (NamingException e) {
			e.printStackTrace();
			result = Integer.valueOf(0); 
		} catch (SQLException e) {
			e.printStackTrace();
			result = Integer.valueOf(0);
		} catch (Exception e) {
			e.printStackTrace();
			result = Integer.valueOf(0);
		} finally {
			if (rs != null) {
			      try { 
			    	  rs.close(); 
			      } catch (SQLException e) {
			    	  
			      }
			      rs = null;
		    }
		    if (stmt != null) {
		      try { 
		    	  	stmt.close();
		    	  } catch (SQLException e) {
		    		  
		    	  }
		      stmt = null;
		    }
			if(con!=null){
				try {
					con.close();
				} catch (SQLException e) {
					
				}
				con = null;
			}
		}
		
		return result;
	}
	
	
	private synchronized static Integer contarPresidentesMesasSinc(){
		Integer result = Integer.valueOf(0);
		Statement stmt = null;
		ResultSet rs = null;
		StringBuilder query = new StringBuilder("");		
		Connection con = null;
		try {
			//creo la coneccion y la sentencia
			con = UtilidadesConexion.getConnectionFromTomcatPool();
			con.setAutoCommit(true);
			stmt = con.createStatement();
			
			//creo la consulta
			query.append("SELECT DISTINCT count(u.usuarios_nombre_usuario) as cantidad ");
			query.append("FROM usuarios u, usuarios_roles ur ");
			query.append("WHERE u.usuarios_nombre_usuario=ur.usuarios_nombre_usuario ")
				.append("AND ur.roles_nombre='").append(Constantes.ROLES_USUARIOS_PRESIDENTE_MESA).append("' ");
			
			//ejecuto la consulta y guardo el resultado en el resultset
			rs = stmt.executeQuery(query.toString());
			if(rs.first()){
				result = rs.getInt("cantidad") ;
			}
		} catch (NamingException e) {
			e.printStackTrace();
			result = Integer.valueOf(0); 
		} catch (SQLException e) {
			e.printStackTrace();
			result = Integer.valueOf(0);
		} catch (Exception e) {
			e.printStackTrace();
			result = Integer.valueOf(0);
		} finally {
			if (rs != null) {
			      try { 
			    	  rs.close(); 
			      } catch (SQLException e) {
			    	  
			      }
			      rs = null;
		    }
		    if (stmt != null) {
		      try { 
		    	  	stmt.close();
		    	  } catch (SQLException e) {
		    		  
		    	  }
		      stmt = null;
		    }
			if(con!=null){
				try {
					con.close();
				} catch (SQLException e) {
					
				}
				con = null;
			}
		}
		
		return result;
	}
	
	private synchronized static List<String> getPresidentesMesasIdsSinc(){
		List<String> result = new ArrayList<String>();
		Statement stmt = null;
		ResultSet rs = null;
		StringBuilder query = new StringBuilder("");		
		Connection con=null;
		try {
			//creo la coneccion y la sentencia
			con = UtilidadesConexion.getConnectionFromTomcatPool();
			con.setAutoCommit(true);
			stmt = con.createStatement();
			
			//creo la consulta
			query.append("SELECT DISTINCT u.usuarios_nombre_usuario as usuarios_nombre_usuario ");
			query.append("FROM usuarios u, usuarios_roles ur ");
			query.append("WHERE u.usuarios_nombre_usuario=ur.usuarios_nombre_usuario ")
				.append("AND ur.roles_nombre='").append(Constantes.ROLES_USUARIOS_PRESIDENTE_MESA).append("' ");
			
			//ejecuto la consulta y guardo el resultado en el resultset
			rs = stmt.executeQuery(query.toString());
			if(rs.first()){
				do{
					result.add(rs.getString("usuarios_nombre_usuario")) ;
				}while(rs.next());
			}
		} catch (NamingException e) {
			e.printStackTrace();
			 result = new ArrayList<String>();
		} catch (SQLException e) {
			e.printStackTrace();
			 result = new ArrayList<String>();
		} catch (Exception e) {
			e.printStackTrace();
			 result = new ArrayList<String>();
		} finally {
			if (rs != null) {
			      try { 
			    	  rs.close(); 
			      } catch (SQLException e) {
			    	  
			      }
			      rs = null;
		    }
		    if (stmt != null) {
		      try { 
		    	  	stmt.close();
		    	  } catch (SQLException e) {
		    		  
		    	  }
		      stmt = null;
		    }
			if(con!=null){
				try {
					con.close();
				} catch (SQLException e) {
					
				}
				con = null;
			}
		}
		
		return result;
	}
	
	private synchronized static Boolean limpiarMesasSinc(Connection con) throws SQLException{
		Boolean result = Boolean.FALSE;
		
		Statement stmt = null;
		StringBuilder query = new StringBuilder("");
		
		try {
			//creo la coneccion y la sentencia
			stmt = con.createStatement();
			
			query.append("DELETE FROM mesas ");
			
			//ejecuto el update
			stmt.executeUpdate(query.toString());
			
			result = Boolean.TRUE;
			
		}finally {
			
		    if (stmt != null) {
		      try { 
		    	  	stmt.close();
		    	  } catch (SQLException e) {
		    		  
		    	  }
		      stmt = null;
		    }
			
		}
	
		return result;
	}
	
	private static synchronized Boolean agregarMesasSinc(Connection con, List<String> idsPresidentesMesas) throws SQLException{
		Boolean result = Boolean.FALSE;
		
		Statement stmt = null;
		StringBuilder query = null;
		
		try {
			//creo la coneccion y la sentencia
			stmt = con.createStatement();
			
			for(int i = 0; i<idsPresidentesMesas.size(); i++){
				query = new StringBuilder("");
				query.append("INSERT INTO mesas (mesas_numero, mesas_presidente_mesa)");
				query.append("VALUES ( ").append(i+1).append(", ")
					.append("'").append(idsPresidentesMesas.get(i)).append("' ) ");
					
				stmt.addBatch(query.toString());
			}
			//ejecuto el update
			stmt.executeBatch();
			
			result = Boolean.TRUE;
			
		}finally {
			
		    if (stmt != null) {
		      try { 
		    	  	stmt.close();
		    	  } catch (SQLException e) {
		    		  
		    	  }
		      stmt = null;
		    }			
		}
		return result;
	}
	
	private synchronized static Boolean asignarEstudiantesMesasSinc(Connection con, Integer cantidadMesas,
			Integer cantidadVotantesPorMesa, Integer cantidadVotantesUltimaMesa ) throws SQLException{
		Boolean result = Boolean.FALSE;
		Statement stmt = null;
		StringBuffer query = null;
		List <Integer> listaIdsEstudiantes = null;
		//creo la coneccion y la sentencia
		
		try {
			
			stmt = con.createStatement();
			
			for(int numeroMesa = 1; numeroMesa<=cantidadMesas.intValue(); numeroMesa++ ){
				//creo la consulta
				query = new StringBuffer("");
				query.append("UPDATE estudiantes e1 ")
					.append("SET e1.estudiantes_numero_mesa='").append(numeroMesa).append("' ");
				query.append("WHERE estudiantes_id IN ( ");
				listaIdsEstudiantes = PropiedadesSistemaConsultas.getEstudiantesIdsListSinc(numeroMesa, cantidadMesas, cantidadVotantesPorMesa, cantidadVotantesUltimaMesa);
				if(listaIdsEstudiantes!=null && listaIdsEstudiantes.size()>0){
					query.append(listaIdsEstudiantes.get(0).toString());
					for(int i = 1; i<listaIdsEstudiantes.size();i++){
							query.append(", ").append(listaIdsEstudiantes.get(i).toString());
					}
					query.append(") ");
					//ejecuto la consulta y guardo el resultado en el resultset
					stmt.executeUpdate(query.toString());
				}else{
					break;
				}
				
			}
			result = Boolean.TRUE;
		}finally {
			
		    if (stmt != null) {
		      try { 
		    	  	stmt.close();
		    	  } catch (SQLException e) {
		    		  
		    	  }
		      stmt = null;
		    }
			
		}
	
		
		return result;
	}
	
	private synchronized static List<Integer> getEstudiantesIdsListSinc(Integer numeroMesa, Integer cantidadMesas, 
			Integer cantidadVotantesPorMesa, Integer cantidadVotantesUltimaMesa ) throws SQLException{
		
		List<Integer> result = new ArrayList<Integer>();
		Statement stmt = null;
		StringBuffer query = null;
		Connection con = null;
		ResultSet rs = null;
		//creo la coneccion y la sentencia
		
		try {
			con = UtilidadesConexion.getConnectionFromTomcatPool();
			con.setAutoCommit(true);
			stmt = con.createStatement();
			
			
			//creo la consulta
			query = new StringBuffer("");
			
			query.append("SELECT DISTINCT e2.estudiantes_id as estudiantes_id ")
				.append("FROM estudiantes e2 ")
				.append("ORDER BY e2.estudiantes_apellidos ASC, e2.estudiantes_nombres ASC, e2.estudiantes_legajo ASC ");
			if(numeroMesa - 1 == 0){
				if(numeroMesa == cantidadMesas.intValue()){
					query.append("LIMIT ").append(cantidadVotantesUltimaMesa.intValue()).append(" ");
				}else{
					query.append("LIMIT ").append(cantidadVotantesPorMesa.intValue()).append(" ");
				}
			}else{
				if(numeroMesa == cantidadMesas.intValue()){
					query.append("LIMIT ").append((numeroMesa-1)*cantidadVotantesPorMesa.intValue())
						.append(", ").append(cantidadVotantesUltimaMesa.intValue()).append(" ");
				}else{
					query.append("LIMIT ").append((numeroMesa-1)*cantidadVotantesPorMesa.intValue())
						.append(", ").append(cantidadVotantesPorMesa.intValue()).append(" ");
				}
			}
			query.append(" ");
			
			//ejecuto la consulta y guardo el resultado en el resultset
			rs = stmt.executeQuery(query.toString());
			
			if(rs!=null && rs.first()){
				do{
					result.add(rs.getInt("estudiantes_id"));
				}while(rs.next());
			}
			
			
		} catch (NamingException e) {
			e.printStackTrace();
			result = new ArrayList<Integer>();
		} catch (SQLException e) {
			e.printStackTrace();
			result = new ArrayList<Integer>();
		} catch (Exception e) {
			e.printStackTrace();
			result = new ArrayList<Integer>();
		}finally {
			if (rs != null) {
			      try { 
			    	  rs.close(); 
			      } catch (SQLException e) {
			    	  
			      }
			      rs = null;
		    }
		    if (stmt != null) {
		      try { 
		    	  	stmt.close();
		    	  } catch (SQLException e) {
		    		  
		    	  }
		      stmt = null;
		    }
			if(con!=null){
				try {
					con.close();
				} catch (SQLException e) {
					
				}
				con = null;
			}
			
		}
	
		
		return result;
	}
	
	private synchronized static Boolean setEstadoVotacionSinc(Connection con, String estadoVotacion) throws SQLException{
		Boolean result = Boolean.FALSE;
		Statement stmt = null;
		StringBuffer query = null;
		
		//creo la coneccion y la sentencia
		
		try {
			
			stmt = con.createStatement();
			
			//creo la consulta
			query = new StringBuffer("");
			query.append("UPDATE propiedades_sistema ")
			.append("SET propiedades_sistema_valor='").append(estadoVotacion).append("' ")
			.append("WHERE propiedades_sistema_nombre='").append(Constantes.PROPIEDADES_SISTEMA_NOMBRE_ESTADO_VOTACION).append("' ");
			//ejecuto la consulta y guardo el resultado en el resultset
			stmt.executeUpdate(query.toString());

			result = Boolean.TRUE;
		}finally {
			
		    if (stmt != null) {
		      try { 
		    	  	stmt.close();
		    	  } catch (SQLException e) {
		    		  
		    	  }
		      stmt = null;
		    }
			
		}
	
		
		return result;
	}
	
	private synchronized static Boolean resetearVotosSinc(Connection con) throws SQLException{
		Boolean result = Boolean.FALSE;
		Statement stmt = null;
		StringBuffer query = new StringBuffer("");
		
		try {
			//creo la consulta
			query.append("UPDATE candidatos ")
			.append("SET candidatos_votos=0 ");
			
			stmt = con.createStatement();
			//ejecuto la consulta y guardo el resultado en el resultset
			stmt.executeUpdate(query.toString());
		
			result = Boolean.TRUE;
		}finally {
			
		    if (stmt != null) {
		      try { 
		    	  	stmt.close();
		    	  } catch (SQLException e) {
		    		  
		    	  }
		      stmt = null;
		    }
			
		}
	
		
		return result;
	}
}
